/*
 * GameManager.java
 *
 * Created on 29 October 2006, 16:33
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package digitrix.fightclub.game;

import digitrix.fightclub.data.DAO;
import digitrix.fightclub.data.PlayerDAO;
import digitrix.network.bt.BTDispatcher;
import digitrix.network.bt.BTListener;
import digitrix.network.bt.BTManager;
import digitrix.network.bt.IBTCallback;
import java.io.IOException;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

/**
 *
 * @author Josh
 */
public class GameManager extends GameCanvas implements Runnable, IManager, IBTCallback {
    
    // game states
    public static final int GS_NEWFIGHT  = 0;
    public static final int GS_FIGHTING  = 1;
    public static final int GS_FIGHTOVER = 2;
    public static final int GS_LOADING   = 4;
    public static final int GS_PAUSED    = 5;
    public static final int GS_RESUME    = 6;
    public static final int GS_SYNC      = 7; // set to this state when the games need to sync with each other
    public static final int GS_FORCE_ROUNDWON = 8;
    
    // game state times
    private static final int GS_TIME_NEWFIGHT   = 1000;
    private static final int GS_TIME_FIGHTOVER  = 1500;    
    private static final int GS_TIME_SYNC_PLAYER_DETAILS = 3500; 
    
    public static final int GAME_PROCESSING_AI      = 0;
    public static final int GAME_PROCESSING_CLIENT  = 1;
    public static final int GAME_PROCESSING_SERVER  = 3;
    
    private static final int MAX_FPS    = 20;
    
    // network gaming constants
    private static final int KEY_STATES_QUEUE_SIZE = 20;
    
    private static GameManager _instance;
    
    private Thread _gameThread = null;
    private World _world = null;
    private Image _imgWallpaper = null;
    private Image _imgArrows = null;
    
    private boolean _running;
    
    // game variables
    private boolean _sleeping = false;
    private boolean _pushingAllowed = true;
    private boolean _wallpaperPainted = false;
    private int _gs = 0;
    private int _prevGS = 0;
    private long _stateTime = 0;
    private long _currTime = 0;
    private int _playerID = 1;
    private String _playerName = "";
    private int _opponentID = 2;
    private String _opponentName = "";
    private int _gameProcess = 0;
    
    // game menu options
    private static final int MENU_FIGHT = 0;
    private static final int MENU_BACK  = 1;
    private static final int MENU_EXIT  = 2;
    private String[] _menuItems = {"FIGHT", "MENU", "EXIT"};
    private int _curMenuItem = 0;
    
    // network gaming variables
    private int[] _localKeystateQueue = null;
    private int _localKSIndex = 0;  // next index to take the keystate from
    private int _localKSNextIndex = 0; // next index to add the new keystate
    
    private int[] _remoteKeystateQueue = null;
    private int _remoteKSIndex = 0;  // next index to take the keystate from
    private int _remoteKSNextIndex = 0; // next index to add the new keystate
    
    private int _gameMode = -1;
    
    private BTManager _btManager = null;
    private FightClub _fc = null;
    
    private boolean _remotePlayerReady = false; 
    private boolean _localPlayerReady = false;
    
    // handle lag 
    private int _lag = 0; 
    private long _tsLocalInputHandled = 0;  // timestamp of local input handled 
    private long _tsSyncWithRemotePlayer = 0; // timestamp to remember the last time we synced with the client 
    
    /** Creates a new instance of GameManager */
    public GameManager( ) {
        super( true );
        _instance = this;
        _fc = FightClub.getInstance();
        
        setCommandListener( _fc );
        
        initGame();
        
        // start games thread
        if ( _gameThread == null || !_gameThread.isAlive() ){
            _gameThread = new Thread( this );
            _running = true;
            _gameThread.start();
        }
    }
    
    public static GameManager getInstance(){
        if( _instance == null )
            _instance = new GameManager();
        
        return _instance;
    }
    
    public void sleep(){
        _sleeping = true;
    }
    
    public void wakeup(){
        _currTime = System.currentTimeMillis();
        _sleeping = false;
        _wallpaperPainted = false; // redraw the wall paper
        synchronized( this ){
            try{
                this.notify();
            } catch( Exception e ){
                System.out.println( "[ERR] GameManager.wakeup(1); " + e.getMessage() );
            }
        }
    }
    
    private void initGame(){
        if( _world == null ){
            try{
                _world = new World( this, this.getWidth(), this.getHeight() );
            } catch( Exception e ){
                System.out.println( "[ERR] GameManager.initGame(1); " + e.getMessage() );
            }
        }
        
        _imgWallpaper = _fc.getWallpaper();
        _imgArrows = _fc.getArrows();
        
        // instantiate keystate queues
        _localKeystateQueue = new int[KEY_STATES_QUEUE_SIZE];
        _remoteKeystateQueue = new int[KEY_STATES_QUEUE_SIZE];
    }
    
    public int getState(){
        return _gs;
    }
    
    public void setState( int newState ){
        System.out.println( "[INFO] GameManager.setState(1); Updating Game State to " + newState );
        
        _stateTime = 0;
        _prevGS = _gs;
        _gs = newState;
        
        switch( _gs ){
            case GS_FIGHTING:{
                _tsLocalInputHandled = _tsSyncWithRemotePlayer = System.currentTimeMillis();                
                break;
            }
            case GS_NEWFIGHT:
                // setup time
                _currTime = System.currentTimeMillis();
                
                // reset keystate keys
                resetKeyStateQueues();
                
                // get the game mode from the midlet
                _gameMode = _fc.getGameMode();
                
                if( _gameMode == FightClub.GAME_MODE_CHALLENGE ){
                    // if game mode is multiplayer then grab the listener and dispatcher and make sure that instantiated
                    _btManager = _fc.getBTManager();
                    
                    _remotePlayerReady = false; 
                    _localPlayerReady = false;

                    if( !_btManager.connectionAlive() ) {
                        _fc.printError( "GameManager.setState(GS_NEWFIGHT)", "BTListener or BTDispatcher are not initilised" );
                        _gameMode = FightClub.GAME_MODE_PRACTICE;
                    }
                    
                    // get the lag 
                    _lag = _btManager.getLag();
                    // only use the lag if lag is greater than the fps 
                    if( _lag < MAX_FPS )
                        _lag = 0; 
                    
                    // load a level
                    _world.initFight( _playerID, _opponentID, true );
                }
                else{
                    // load a level
                _world.initFight( _playerID, _opponentID, false );
                }
                
                if( _sleeping )
                    wakeup();
                break;
            case GS_PAUSED:
                _sleeping = true;
                break;
            case GS_RESUME:
                // setup time
                _currTime = System.currentTimeMillis();
                
                if( _prevGS == GS_SYNC )
                    resetKeyStateQueues();
                
                _gs = GS_FIGHTING;
                
                if( _sleeping )
                    wakeup();
                break;
            case GS_FIGHTOVER:
            case GS_FORCE_ROUNDWON: 
                // reset menu item
                _curMenuItem = MENU_FIGHT;
                
                // determine who won
                if( !_world.timeRanOut() ){
                    if( _world.getPlayer().getHealth() > _world.getOpponent().getHealth() )
                        _world.playerWon();
                    else
                        _world.opponentWon();
                }
                
                // determine if thats the end of the game
                if( _world.getRound() < World.NO_ROUNDS ){
                    _gs = GS_NEWFIGHT; // change state
                    _currTime = System.currentTimeMillis(); // setup time
                    
                    // notify remote user if we're playing a bt connected game 
                    if( _gameMode == FightClub.GAME_MODE_CHALLENGE && _gs != GS_FORCE_ROUNDWON ){
                        if( _world.getPlayer().getHealth() > _world.getOpponent().getHealth() )
                            _btManager.syncRoundOver( BTManager.ROUND_OVER_LOCAL_WON );
                        else
                            _btManager.syncRoundOver( BTManager.ROUND_OVER_REMOTE_WON );                                                
                    }
                    
                    _world.nextRound(); // restart fight
                } else{
                    // save player stats
                    if( _world.winner() == World.PLAYER_WINS )
                        DAO.playerWins();
                    else if( _world.winner() == World.OPPONENT_WINS )
                        DAO.playerLoses();
                    else
                        DAO.draw();
                }
                break;
            case GS_SYNC:                
                // TODO: flush keystate queues for both local user and remote user
                
                break;
        }
    }
    
    public void run() {
        _currTime = System.currentTimeMillis();
        
        long endTime;
        
        while( _running ){
            long elapsedTime = System.currentTimeMillis() - _currTime;
            _currTime += elapsedTime;
            
            // sleep game thread not focused or set to sleep
            if( _sleeping || FightClub.getActivatedDisplayable() != this && !_running ){
                System.out.println( "[INFO] GameManager.run(1); Going to sleep" );
                _sleeping = true;
                synchronized( this ){
                    try{
                        this.wait();
                    } catch( Exception e ){
                    }
                }
                System.out.println( "[INFO] GameManager.run(1); Back to life!" );
            }
            
            if( !_running )
                break;
            
            // process state
            if( processGame() ){
            _stateTime += elapsedTime;
                if( _gs == GS_NEWFIGHT ){
                    if( _stateTime > GS_TIME_NEWFIGHT )
                        setState( GS_FIGHTING );
                }
            }
            
            // process game
            if( _gs != GS_SYNC ){
                checkUserInput( elapsedTime );
                processInput();
            }
            
            if( _gs == GS_FIGHTING ){
                processGameActors( elapsedTime );
                
                if( _gameMode == FightClub.GAME_MODE_CHALLENGE && _btManager.isServer() ){
                    if( (System.currentTimeMillis() - _tsSyncWithRemotePlayer) > GS_TIME_SYNC_PLAYER_DETAILS ){
                        syncPlayerDetails(); 
                    }
                }
            }
            render();
            
            syncGameLoop( _currTime );
            
        }
        
        FightClub.printDebug( "GameManager", "run", "GameManager stopped" );
    }
    
    public void stop(){
        _running = false;
        synchronized( this ){
            try{
                this.notify();
            } catch( Exception e ){}
        }
    }
    
    //<editor-fold defaultstate="collapsed" desc="keystate queue handling methods">
    
    /** set the indexes to the start if of the queues **/
    private void resetKeyStateQueues(){
        _localKSIndex = 0;
        _localKSNextIndex = 0;
        _remoteKSIndex = 0;
        _remoteKSNextIndex = 0;
    }
    
    public int getNextLocalKS(){
        // if the _localKSIndex == _localKSNextIndex then there are no keystates to process so return -1
        if( _localKSIndex == _localKSNextIndex )
            return -1;
        
        // get the keystate value
        int keyState = _localKeystateQueue[ _localKSIndex ];
        
        _localKSIndex++; // move to the next keystate value
        
        // if we have reached the end of the array then set the index back to zero
        if( _localKSIndex >= _localKeystateQueue.length )
            _localKSIndex = 0;
        
        return keyState;
    }
    
    public void setNextLocalKS( int keystate ){
        // make sure it is a valid keystate ie the keystate actually has some key presses in it, eg if the
        // keystate has either/any of the following keys then it is a valid keystate and will be added to the queue
        // left, right, up, down, or/and fire
        if( !isKeyStateValid( keystate ) )
            return;
        
        _localKeystateQueue[_localKSNextIndex] = keystate;
        _localKSNextIndex++;
        
        
        
        // if the new index is the same as index then deincrement the nextindex (essentially overriding the
        // state just set BUT this shouldn't happen (hopefully)
        // TODO: better handling required
        //if( _localKSNextIndex == _localKSIndex )
        //    _localKSNextIndex--;
        
        // if we have reached the end of the array then start back at index 0
        if( _localKSNextIndex >= _localKeystateQueue.length )
            _localKSNextIndex = 0;
    }
    
    public int getNextRemoteKS(){
        // if the _localKSIndex == _localKSNextIndex then there are no keystates to process so return -1
        if( _remoteKSIndex == _remoteKSNextIndex )
            return -1;
        
        // get the keystate value
        int keyState = _remoteKeystateQueue[ _remoteKSIndex ];
        
        _remoteKSIndex++; // move to the next keystate value
        
        // if we have reached the end of the array then set the index back to zero
        if( _remoteKSIndex >= _remoteKeystateQueue.length )
            _remoteKSIndex = 0;
        
        return keyState;
    }
    
    public void setNextRemoteKS( int keystate ){
        
        // reverse left and right (this is done by first testing whether a direction was pressed, 
        // if so then unflag that bit and set the reverse bit ie if left was pressed then unflag that 
        // bit and then flag the right bit
        if( (keystate & LEFT_PRESSED) != 0 ){
            // unset left
            keystate &= ~LEFT_PRESSED;
            // set right
            keystate |= RIGHT_PRESSED;            
        }
        else if( (keystate & RIGHT_PRESSED) != 0 ){
            // unset right 
            keystate &= ~RIGHT_PRESSED;            
            // set left
            keystate |= LEFT_PRESSED;            
        }
        
        _remoteKeystateQueue[_remoteKSNextIndex] = keystate;        
        _remoteKSNextIndex++;
        
        // if the new index is the same as index then deincrement the nextindex (essentially overriding the
        // state just set BUT this shouldn't happen (hopefully)
        // TODO: better handling required
        //if( _remoteKSNextIndex == _remoteKSIndex )
        //    _remoteKSNextIndex--;
        
        // if we have reached the end of the array then start back at index 0
        if( _remoteKSNextIndex >= _remoteKeystateQueue.length )
            _remoteKSNextIndex = 0;
    }
    
    /**
     *
     **/
    private boolean isKeyStateValid( int keyState ){
        if( ( keyState & FIRE_PRESSED ) != 0 )
            return true;
        else if( ( keyState & LEFT_PRESSED ) != 0 )
            return true;
        else if( ( keyState & RIGHT_PRESSED ) != 0 )
            return true;
        else if( ( keyState & UP_PRESSED ) != 0 )
            return true;
        else if( ( keyState & DOWN_PRESSED ) != 0 )
            return true;
        
        return false;
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="helper methods">
    
    private boolean processGame(){
        if( _gameMode == FightClub.GAME_MODE_PRACTICE )
            return true;
        else{
            if( !_localPlayerReady ){
                _localPlayerReady = true; 
                _btManager.dispatchNonParamEvent( BTManager.EVT_FIGHT ); 
            }
            
            return _localPlayerReady && _remotePlayerReady;  
        }
    }
    
    private void checkUserInput( long elapsedTime ){
        // players move
        int keyState = getKeyStates();
        if( _gs == GS_FIGHTING ){
            if( _gameMode == FightClub.GAME_MODE_PRACTICE ){
                setNextLocalKS( keyState );
            } else{
                if( validKeystate( keyState ) ){
                    _fc.printDebug( "GameManager", "setNextLocalKS", "adding keystate to the dispatcher" );
                    
                    // add ks to dispatcher
                    getBTManager().dispatchGameData( keyState );
                    setNextLocalKS( keyState ); 
                }
            }
        } else if( _gs == GS_FIGHTOVER ){
            if( (keyState & GameManager.FIRE_PRESSED ) != 0 ){
                // depending on the current menu item selected
                if( _curMenuItem == MENU_FIGHT ){
                    _gs = GS_NEWFIGHT;
                    _world.fightAgain();
                } else if( _curMenuItem == MENU_BACK ){
                    _fc.activateMenuManager();
                } else if( _curMenuItem == MENU_EXIT ){
                    _fc.exit();
                }
            } else if( (keyState & GameManager.RIGHT_PRESSED ) != 0 ){
                _curMenuItem++;
                if( _curMenuItem > 2 )
                    _curMenuItem = 0;
            } else if( (keyState & GameManager.LEFT_PRESSED ) != 0 ){
                _curMenuItem--;
                if( _curMenuItem < 0 )
                    _curMenuItem = 2;
            }
        }
        
    }
    
    private boolean validKeystate( int keyState ){
        if( (keyState & GameManager.FIRE_PRESSED ) != 0 ){
            return true;
        } else if( (keyState & GameManager.RIGHT_PRESSED ) != 0 ){
            return true;
        } else if( (keyState & GameManager.LEFT_PRESSED ) != 0 ){
            return true;
        } else if( (keyState & GameManager.UP_PRESSED ) != 0 ){
            return true;
        } else if( (keyState & GameManager.DOWN_PRESSED ) != 0 ){
            return true;
        } else {
            return false;
        }
    }
    
    /**
     *
     **/
    public void processInput(){
        
        // process local players move
        if( _lag == 0 || ((System.currentTimeMillis() - _tsLocalInputHandled) >= _lag) ){
            _tsLocalInputHandled = System.currentTimeMillis(); 
            
            int localKS = getNextLocalKS();

            if( localKS != -1 )
                _world.getPlayer().handleInput( localKS );
        }
        
        // process opponents (computer or remote player) move
        if( _world.getOpponent() instanceof AIFighter && _gameMode == FightClub.GAME_MODE_PRACTICE ){
            ((AIFighter)_world.getOpponent()).think();
        } else if( _gameMode == FightClub.GAME_MODE_CHALLENGE ){
            int remoteKS = getNextRemoteKS();
            
            if( remoteKS != -1 )
                _world.getOpponent().handleInput( remoteKS );
        }
    }
    
    private void processGameActors( long elapsedTime ){
        
        // tick tock...
        _world.getPlayer().tick( elapsedTime );
        _world.getOpponent().tick( elapsedTime );
        
        // test for collisions
        if( _world.getPlayer().collidesWith( _world.getOpponent(), false ) ){
            if( _world.getPlayer().getFightingDamage() > 0 && _world.getOpponent().getFightingDamage() > 0 ){
                // if both are attacking them do nothing - for now at least.
            } else if( _world.getPlayer().getFightingDamage() > 0 ){
                _world.getOpponent().takeDamage( _world.getPlayer().getFightingDamage() );
                _world.updateOpponentsEnergyBar();
            } else if( _world.getOpponent().getFightingDamage() > 0 ){
                _world.getPlayer().takeDamage( _world.getOpponent().getFightingDamage() );
                _world.updatePlayersEnergyBar();
            } else{
                if( _world.getPlayer().collidesWith( _world.getOpponent(), true ) ){
                    // if neither are attacking them set their positions so they're not collidiing
                    if( !_world.getPlayer().inFightingState() && !_world.getOpponent().inFightingState() ){
                        // keep the leftActor on the left and the rightActor on the right
                        Actor leftActor = ( !_world.getPlayer().isFacingLeft() ? _world.getPlayer() : _world.getOpponent() );
                        Actor rightActor = ( !_world.getPlayer().isFacingLeft() ? _world.getOpponent() : _world.getPlayer() );
                        
                        int dif = rightActor.getX() - (leftActor.getX() + leftActor.getWidth());
                        
                        if( _pushingAllowed ){
                            leftActor.forcedMove( dif-1, 0 );
                            rightActor.forcedMove( -1*dif+1, 0 );
                        } else if( leftActor.movedLastTick() && !rightActor.movedLastTick() ){
                            leftActor.forcedMove( dif-1, 0 );
                        } else if( !leftActor.movedLastTick() && rightActor.movedLastTick() ){
                            rightActor.forcedMove( -1*dif+1, 0 );
                        } else{
                            leftActor.forcedMove( dif-1, 0 );
                            rightActor.forcedMove( -1*dif+1, 0 );
                        }
                    }
                }
            }
        }
        
        _world.tick( elapsedTime );
        _world.tickSpecialEffects( elapsedTime );
    }
    
    private void render(){
        if( FightClub.getActivatedDisplayable() != this )
            return;
        
        Graphics g = getGraphics();
        
        // draw wallpaper
        if(  _imgWallpaper != null && !_wallpaperPainted ){
            
            g.setColor( 0xffffff );
            g.fillRect( 0, 0, getWidth(), getHeight() );
            
            int imgWidth = _imgWallpaper.getWidth();
            int imgHeight = _imgWallpaper.getHeight();
            
            for( int i = 0; i < getWidth(); i += imgWidth ){
                for( int z = 0; z < getHeight(); z += imgHeight ){
                    g.drawImage( _imgWallpaper, i, z, Graphics.LEFT | Graphics.TOP );
                }
            }
            
            _wallpaperPainted = true;
        }
        
        // clear screen
        g.setColor( 0xffffff );
        World world = World.getInstance();
        
        // draw world
        _world.paint( g, 0, 0, getWidth(), getHeight() );
        
        // draw state specific details
        if( _gs == GS_NEWFIGHT ){
            if( _world.getRound() < World.NO_ROUNDS )
                _fc.getGameFont().drawLargeString( "FIGHT", _world.getWorldsHorzCenter()-30, _world.getWorldsVertCenter()-6, g );
            else
                _fc.getGameFont().drawLargeString( "FINAL ROUND", _world.getWorldsHorzCenter()-66, _world.getWorldsVertCenter()-6, g );
        } else if( _gs == GS_FIGHTOVER ){
            // notify user who won
            int winner = _world.winner();
            if( winner == World.PLAYER_WINS )
                _fc.getGameFont().drawLargeString( "YOU WIN", _world.getWorldsHorzCenter()-42, _world.getWorldsVertCenter()-6, g );
            else if( winner == World.OPPONENT_WINS )
                _fc.getGameFont().drawLargeString( "YOU LOSE", _world.getWorldsHorzCenter()-48, _world.getWorldsVertCenter()-6, g );
            else
                _fc.getGameFont().drawLargeString( "DRAW", _world.getWorldsHorzCenter()-24, _world.getWorldsVertCenter()-6, g );
            
            // display the menu
            int pos1 = _world.getWorldsHorzCenter() - (_menuItems[_curMenuItem].length()*7 + 14);
            int pos2 = _world.getWorldsHorzCenter() - _menuItems[_curMenuItem].length()*6;
            int pos3 = _world.getWorldsHorzCenter() + _menuItems[_curMenuItem].length()*8;
            
            g.setClip( pos1, _world.getWorldsVertCenter()+14, 14, 12);
            g.drawImage( _imgArrows, pos1, _world.getWorldsVertCenter()+14, Graphics.TOP | Graphics.LEFT );
            
            g.setClip( pos3, _world.getWorldsVertCenter()+14, 14, 12);
            g.drawImage( _imgArrows, pos3-14, _world.getWorldsVertCenter()+14, Graphics.TOP | Graphics.LEFT );
            
            g.setClip( 0, 0, getWidth(), getHeight() );
            _fc.getGameFont().drawLargeString( _menuItems[_curMenuItem], pos2, _world.getWorldsVertCenter()+14, g );
            
        } else if( _gs == GS_SYNC ){
            _fc.getGameFont().drawLargeString( "SYNC GAME", _world.getWorldsHorzCenter()-42, _world.getWorldsVertCenter()-6, g );
        }
        
        flushGraphics();
        
    }
    
    private void syncGameLoop( long currTime ){
        // sleep if necessary to make a smooth framerate
        long endTime = System.currentTimeMillis() - currTime;
        //System.out.println( "Start Time = " + startTime + " End Time = " + endTime );
        if (endTime < (1000 / MAX_FPS)) {
            try {
                // frames per second
                _gameThread.sleep((1000 / MAX_FPS) - endTime);
            } catch (Exception e) { }
        } else {
            try {
                _gameThread.yield();
            } catch (Exception e) { }
        }
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="Getters and Setters">
    
    public int getGameMode(){
        return _gameMode; 
    }
    
    public int getPlayerID(){
        return _playerID;
    }
    
    public void setPlayerID( int id ){
        _playerID = id;
    }
    
    public int getOpponentID(){
        return _opponentID;
    }
    
    public void setOpponentID( int id ){
        _opponentID = id;
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="IBTCallback implementation and other bt helper methods">
    
    private BTManager getBTManager(){
        if( _btManager == null )
            _btManager = BTManager.getInstance();
        
        return _btManager;
    }
    
    public void btSetStatus(String status) {
        //TODO: display the actual message to the user
        _fc.printDebug( "GameManager", "btSetStatus", status );
    }
    
    /**
     * place opponents keystate onto the queue
     **/
    public void btEvent(byte evtType, int evtDetails) {
        if( evtType == BTManager.EVT_GAME_DATA ){
            _fc.printDebug( "GameManager", "btEvent", "game data has just come in" ); 
            setNextRemoteKS( evtDetails );
        }
        else if( evtType == BTManager.EVT_FIGHT ){
            _remotePlayerReady = true; 
        } 
        else if( evtType == BTManager.EVT_SYNC_ROUND_OVER ){
            _fc.printDebug( "GameManager", "btEvent", "SYNC_ROUND_OVER EVENT RECEIVED" ); 
            
            // if on a new round already then ignore this event otherwise set the status 
            if( _gs != GS_NEWFIGHT ){
                setState( GS_FORCE_ROUNDWON ); 
            }
        }
        else if( evtType == BTManager.EVT_PAUSE ){
            setState( GS_PAUSED ); 
        }
    }
    
    /**
     * if we're the client then response back to the server with our current details 
     **/
    public void btSyncEvent(int posX, int posY, int health) {
        if( !_btManager.isServer() ){
            syncPlayerDetails(); 
        }
        
        // reverse the opponents position from we have got as the player fights on the same side as us
        _world.getOpponent().setPosition( _world.getWorldWidth() - posX, posY );
        _world.getOpponent().setHealth( health );
    }
    
    private void syncPlayerDetails(){
        _tsSyncWithRemotePlayer = System.currentTimeMillis(); 
        _fc.printDebug( "GameManager", "syncPlayerDetails", "performing position etc sync with the remote player - strange effects so not implementing" ); 
        //_btManager.syncPlayerDetails( _world.getPlayer().getX(), _world.getPlayer().getY(), _world.getPlayer().getHealth() );
    }
    
    public void btPlayerDetails(String details) {
        // only implemented in the MenuManager
    }
    
    public void btPlayersFound( String[] players ){
        // only implemented in the MenuManager
    }
    
    public void btFightRequest(String playersName) {
        // only implemented in the MenuManager
    }
    //</editor-fold>
    
}
